/**
 * Written By: MinHo Kim (minho.kim.korea@gmail.com)
 * Copyright (C) 2011, MinHo Kim, Software Expert Program, KAIST University, Seoul, Korea.
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published 
 * by the Free Software Foundation; version 2 of the License.
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU General Public License for more details.
 */
package kaist.sep502.tsp.model;

import java.util.ArrayList;
import java.util.List;

import kaist.sep502.tsp.util.TspUtil;



/**
 * @author minho kim
 * use public members for performance, but it should be modified within this class.
 */
public class CityPath implements Cloneable, Comparable<Object> {
	public double gx = 0.0;
	public double hx = 0.0;
	public List<Integer> tourHistory;

	/**
	 * 출발점 설정 시에만 생성자를 사용한다.
	 * @param departure
	 */
	public CityPath(Problem problem, int cityNo) {
		tourHistory = new ArrayList<Integer>();
		tourHistory.add(cityNo);
	}

	/**
	 * 최초 생성에는 사용하지 않고 도시 이동 간에만 사용.
	 * @param problem
	 * @param currentCityNo
	 * @param hx
	 * @throws Exception 
	 */
	public void moveTo(Problem problem, int currentCityNo, double hx) throws Exception{
		City one = problem.getCity(tourHistory.get(tourHistory.size()-1));
		City two = problem.getCity(currentCityNo);
//		this.gx += problem.getDistance(tourHistory.get(tourHistory.size()-1), currentCityNo);
		this.gx += problem.calculateDistance(one, two);
		this.hx = hx;
		
		tourHistory.add(currentCityNo);
	}
	
	public void addHx(double hx){
		this.hx += hx;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Object o) {
		CityPath operand = (CityPath) o;
		
//		if(tourHistory.size() > ){	// UCS 에 영향을 미치는 원인을 파악 필요.
			if(tourHistory.size() > operand.tourHistory.size()){
				return -1;
			} else if(tourHistory.size() < operand.tourHistory.size()){
				return 1;
			}
//		}
		
		if(this.getPathCost() > operand.getPathCost()){
			return 1;
		} else if(this.getPathCost() <= operand.getPathCost()){
			return -1;
		} else {
			return 0;
		}
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	@Override
	public CityPath clone(){
		CityPath clone = null;
		try {
			clone = (CityPath) super.clone();
			clone.gx = this.gx;
			clone.hx = this.hx;
			int size = this.tourHistory.size();
			clone.tourHistory = new ArrayList<Integer>();
			for(int i=0; i<size; i++){
				clone.tourHistory.add(new Integer(this.tourHistory.get(i)));
			}
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return clone;
	}

	public CharSequence getPathListString() {
		StringBuilder sb = new StringBuilder();
		int size = tourHistory.size();
		for (int i = 0; i < size; i++) {
			if (i == 0) {
				sb.append(tourHistory.get(i));
			} else {
				sb.append("-").append(tourHistory.get(i));
			}
		}

		return sb;
	}
	
	public int getLastCity(){
		return tourHistory.get(tourHistory.size() -1);
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[").append(getPathListString()).append("] ").append(TspUtil.formatDouble(getPathCost()));
		return sb.toString();
	}

	/**
	 * @return
	 */
	public double getPathCost() {
//		return TspUtil.formatDouble((double) gx + hx);
		return gx + hx;
	}
}
